package cn.reinforce.util.express;

import cn.reinforce.util.express.exception.SFException;
import cn.reinforce.util.express.model.sf.*;
import cn.reinforce.util.http.HttpClientUtil;
import cn.reinforce.util.http.model.HttpResult;
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import org.apache.commons.codec.binary.Base64;
import org.apache.commons.lang3.StringUtils;

import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
import java.security.MessageDigest;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.UUID;

/**
 * @author 幻幻Fate
 * @date 2023/2/15
 */
public class SFUtil {

    private SFUtil() {
    }

    public static SFOrderResponse createOrder(SFOrder order) {

        Gson gson = new GsonBuilder().create();
        System.out.println(gson.toJson(order));
        SFResultData sfResultData = serviceRequest("EXP_RECE_CREATE_ORDER", gson.toJson(order));

        SFOrderResponse sfOrderResponse = gson.fromJson(gson.toJson(sfResultData.getMsgData()), SFOrderResponse.class);

        return sfOrderResponse;
    }

    public static SFOrderResponse cancelOrder(String orderId) {
        Gson gson = new GsonBuilder().create();
        SFOrder order = new SFOrder();
        order.setOrderId(orderId);
        order.setDealType(SFOrder.DEAL_TYPE_CANCEL);
        SFResultData sfResultData = serviceRequest("EXP_RECE_UPDATE_ORDER", gson.toJson(order));

        SFOrderResponse sfOrderResponse = gson.fromJson(gson.toJson(sfResultData.getMsgData()), SFOrderResponse.class);

        return sfOrderResponse;
    }

    /**
     * 因Internet环境下，网络不是绝对可靠，用户系统下订单到顺丰后，不一定可以收到顺丰系统返回的数据，此接口用于在未收到返回数据时，查询订单创建接口客户订单当前的处理情况
     *
     * @param orderId
     * @return
     * @throws UnsupportedEncodingException
     */
    public static SFOrderResponse searchOrder(String orderId) {
        Gson gson = new GsonBuilder().create();
        SFOrderSearch orderSearch = new SFOrderSearch();
        orderSearch.setOrderId(orderId);
        SFResultData sfResultData = serviceRequest("EXP_RECE_SEARCH_ORDER_RESP", gson.toJson(orderSearch));

        SFOrderResponse sfOrderResponse = gson.fromJson(gson.toJson(sfResultData.getMsgData()), SFOrderResponse.class);

        return sfOrderResponse;
    }


    public static List<SFRouteResponse> getRoute(String waybillNo) {

        Gson gson = new GsonBuilder().setDateFormat("yyyy-MM-dd HH:mm:ss").create();
        SFRouteRequest sfRouteRequest = new SFRouteRequest();
        sfRouteRequest.getTrackingNumber().add(waybillNo);
        SFResultData sfResultData = serviceRequest("EXP_RECE_SEARCH_ROUTES", gson.toJson(sfRouteRequest));

        sfResultData.setRouteResps(gson.fromJson(gson.toJson(sfResultData.getMsgData()), SFResultData.class).getRouteResps());

        return sfResultData.getRouteResps();
    }

    public static SFResultData serviceRequest(String code, String msgData) {
        SF sf = SF.INSTANCE;

        Map<String, Object> params = new HashMap<>();

        String timeStamp = String.valueOf(System.currentTimeMillis());

        // 顾客编码 ，对应丰桥上获取的clientCode
        params.put("partnerID", sf.getPartnerId());
        params.put("requestID", UUID.randomUUID().toString().replace("-", ""));
        // 接口服务码
        params.put("serviceCode", code);
        params.put("timestamp", timeStamp);
        params.put("msgData", msgData);
        try {
            params.put("msgDigest", sign(msgData, timeStamp, sf.getKey()));
        } catch (UnsupportedEncodingException e) {
            throw new SFException(e);
        }

//        System.out.println(params);

        Map<String, String> headers = new HashMap<>();
        headers.put("Content-type", "application/x-www-form-urlencoded");

        HttpResult result = HttpClientUtil.post(sf.getServiceUrl(), params, headers, "", false);

//        System.out.println(result);

        Gson gson = new GsonBuilder().create();
        SFResponse sfResponse = gson.fromJson(result.getResult(), SFResponse.class);
        SFResultData sfResultData = gson.fromJson(sfResponse.getApiResultData(), SFResultData.class);

        if (!StringUtils.equals(sfResponse.getApiResultCode(), "A1000")) {
            throw new SFException(sfResponse.getApiErrorMsg());
        }

        if (!sfResultData.getSuccess()) {
            throw new SFException(sfResultData.getErrorMsg());
        }

        return sfResultData;
    }

    public static String getAccessToken() {
        SF sf = SF.INSTANCE;

        Map<String, Object> params = new HashMap<>();


        params.put("partnerID", sf.getPartnerId());
        params.put("secret", sf.getKey());
        params.put("grantType", "password");

        Map<String, String> headers = new HashMap<>();
        headers.put("Content-type", "application/x-www-form-urlencoded;charset=UTF-8");

        HttpResult result = HttpClientUtil.post(sf.getOauth2Url(), params, headers, "", false);

        System.out.println(result);

        if (result == null) {
            return null;
        }

        Gson gson = new GsonBuilder().create();
        SFResponse sfResponse = gson.fromJson(result.getResult(), SFResponse.class);

        return sfResponse.getAccessToken();
    }

    private static String sign(String msgData, String timeStamp, String md5Key) throws UnsupportedEncodingException {
        String stringToSign = URLEncoder.encode(msgData + timeStamp + md5Key, StandardCharsets.UTF_8);
        return encodeBase64(md5Encrypt(stringToSign));
    }

    private static byte[] md5Encrypt(String encryptStr) {
        try {
            MessageDigest md5 = MessageDigest.getInstance("MD5");
            md5.update(encryptStr.getBytes(StandardCharsets.UTF_8));
            return md5.digest();
        } catch (Exception var2) {
            throw new RuntimeException(var2);
        }
    }

    private static String encodeBase64(byte[] data) {
        return (new Base64()).encodeAsString(data);
    }
}
